package com.intelligent.utils;

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.List;

/**
 * Excel工具类
 * 提供Excel文件的生成和导出功能
 */
public class ExcelUtils {

    /**
     * 导出数据到Excel文件
     *
     * @param response HTTP响应对象
     * @param fileName 文件名（不包含扩展名）
     * @param sheetName 工作表名称
     * @param headers 表头数组
     * @param dataList 数据列表
     * @param dataExtractor 数据提取器
     * @param <T> 数据类型
     * @throws IOException IO异常
     */
    public static <T> void exportToExcel(HttpServletResponse response,
                                        String fileName,
                                        String sheetName,
                                        String[] headers,
                                        List<T> dataList,
                                        DataExtractor<T> dataExtractor) throws IOException {
        // 设置响应头
        String fullFileName = fileName + ".xlsx";
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setHeader("Content-Disposition", "attachment; filename=" + 
                          new String(fullFileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1));
        
        // 创建工作簿
        try (Workbook workbook = new XSSFWorkbook()) {
            Sheet sheet = workbook.createSheet(sheetName);
            
            // 创建标题行样式
            CellStyle headerStyle = createHeaderStyle(workbook);
            
            // 创建标题行
            Row headerRow = sheet.createRow(0);
            for (int i = 0; i < headers.length; i++) {
                Cell cell = headerRow.createCell(i);
                cell.setCellValue(headers[i]);
                cell.setCellStyle(headerStyle);
                sheet.setColumnWidth(i, 15 * 256); // 设置列宽
            }
            
            // 创建数据行样式
            CellStyle dataStyle = createDataStyle(workbook);
            
            // 填充数据
            for (int i = 0; i < dataList.size(); i++) {
                T data = dataList.get(i);
                Row row = sheet.createRow(i + 1);
                
                Object[] values = dataExtractor.extract(data);
                for (int j = 0; j < values.length; j++) {
                    Cell cell = row.createCell(j);
                    setCellValue(cell, values[j]);
                    cell.setCellStyle(dataStyle);
                }
            }
            
            // 写入响应流
            try (OutputStream outputStream = response.getOutputStream()) {
                workbook.write(outputStream);
                outputStream.flush();
            }
        }
    }

    /**
     * 创建标题行样式
     *
     * @param workbook 工作簿
     * @return 标题行样式
     */
    private static CellStyle createHeaderStyle(Workbook workbook) {
        CellStyle headerStyle = workbook.createCellStyle();
        Font headerFont = workbook.createFont();
        headerFont.setBold(true);
        headerStyle.setFont(headerFont);
        headerStyle.setAlignment(HorizontalAlignment.CENTER);
        headerStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        headerStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
        headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        return headerStyle;
    }

    /**
     * 创建数据行样式
     *
     * @param workbook 工作簿
     * @return 数据行样式
     */
    private static CellStyle createDataStyle(Workbook workbook) {
        CellStyle dataStyle = workbook.createCellStyle();
        dataStyle.setAlignment(HorizontalAlignment.CENTER);
        dataStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        return dataStyle;
    }

    /**
     * 设置单元格值
     *
     * @param cell 单元格
     * @param value 值
     */
    private static void setCellValue(Cell cell, Object value) {
        if (value == null) {
            cell.setCellValue("");
        } else if (value instanceof Number) {
            if (value instanceof Integer || value instanceof Long) {
                cell.setCellValue(((Number) value).longValue());
            } else {
                cell.setCellValue(((Number) value).doubleValue());
            }
        } else if (value instanceof Boolean) {
            cell.setCellValue((Boolean) value);
        } else {
            cell.setCellValue(value.toString());
        }
    }

    /**
     * 数据提取器接口
     *
     * @param <T> 数据类型
     */
    @FunctionalInterface
    public interface DataExtractor<T> {
        /**
         * 从数据对象中提取值数组
         *
         * @param data 数据对象
         * @return 值数组
         */
        Object[] extract(T data);
    }
} 